﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.IO;

namespace Home.ArtDB
{
    /// <summary>
    /// Pfad zu Windows-Verzeichnisse
    /// </summary>
    public class SpecialFolder
    {
        /// <summary>
        /// Definition of special folder
        /// </summary>
        public enum SpecialFolderNames
        {
            /// <summary>desktop</summary>
            CSIDL_DESKTOP = 0x0000,
            /// <summary>Internet Explorer (icon on desktop)</summary>
            CSIDL_INTERNET = 0x0001,
            /// <summary>Start Menu\Programs</summary>
            CSIDL_PROGRAMS = 0x0002,
            /// <summary>My Computer\Control Panel</summary>
            CSIDL_CONTROLS = 0x0003,
            /// <summary>My Computer\Printers</summary>
            CSIDL_PRINTERS = 0x0004,
            /// <summary>My Documents</summary>
            CSIDL_PERSONAL = 0x0005,
            /// <summary>[user name]\Favorites</summary>
            CSIDL_FAVORITES = 0x0006,
            /// <summary>Start Menu\Programs\Startup</summary>
            CSIDL_STARTUP = 0x0007,
            /// <summary>[user name]\Recent</summary>
            CSIDL_RECENT = 0x0008,
            /// <summary>[user name]\SendTo</summary>
            CSIDL_SENDTO = 0x0009,
            /// <summary>[desktop]\Recycle Bin</summary>
            CSIDL_BITBUCKET = 0x000a,
            /// <summary>[user name]\Start Menu</summary>
            CSIDL_STARTMENU = 0x000b,
            /// <summary>Personal was just a silly name for My Documents</summary>
            CSIDL_MYDOCUMENTS = CSIDL_PERSONAL,
            /// <summary>"My Music" folder</summary>
            CSIDL_MYMUSIC = 0x000d,
            /// <summary>"My Videos" folder</summary>
            CSIDL_MYVIDEO = 0x000e,
            /// <summary>[user name]\Desktop</summary>
            CSIDL_DESKTOPDIRECTORY = 0x0010,
            /// <summary>My Computer</summary>
            CSIDL_DRIVES = 0x0011,
            /// <summary>Network Neighborhood (My Network Places)</summary>
            CSIDL_NETWORK = 0x0012,
            /// <summary>[user name]\nethood</summary>
            CSIDL_NETHOOD = 0x0013,
            /// <summary>windows\fonts</summary>
            CSIDL_FONTS = 0x0014,
            /// <summary></summary>
            CSIDL_TEMPLATES = 0x0015,
            /// <summary>All Users\Start Menu</summary>
            CSIDL_COMMON_STARTMENU = 0x0016,
            /// <summary>All Users\Start Menu\Programs</summary>
            CSIDL_COMMON_PROGRAMS = 0x0017,
            /// <summary>All Users\Startup</summary>
            CSIDL_COMMON_STARTUP = 0x0018,
            /// <summary>All Users\Desktop</summary>
            CSIDL_COMMON_DESKTOPDIRECTORY = 0x0019,
            /// <summary>[user name]\Application Data</summary>
            CSIDL_APPDATA = 0x001a,
            /// <summary>[user name]\PrintHood</summary>
            CSIDL_PRINTHOOD = 0x001b,
            /// <summary>[user name]\Local Settings\Applicaiton Data (non roaming)</summary>
            CSIDL_LOCAL_APPDATA = 0x001c,
            /// <summary>non localized startup</summary>
            CSIDL_ALTSTARTUP = 0x001d,
            /// <summary>non localized common startup</summary>
            CSIDL_COMMON_ALTSTARTUP = 0x001e,
            /// <summary></summary>
            CSIDL_COMMON_FAVORITES = 0x001f,
            /// <summary></summary>
            CSIDL_INTERNET_CACHE = 0x0020,
            /// <summary></summary>
            CSIDL_COOKIES = 0x0021,
            /// <summary></summary>
            CSIDL_HISTORY = 0x0022,
            /// <summary>All Users\Application Data</summary>
            CSIDL_COMMON_APPDATA = 0x0023,
            /// <summary>GetWindowsDirectory()</summary>
            CSIDL_WINDOWS = 0x0024,
            /// <summary>GetSystemDirectory()</summary>
            CSIDL_SYSTEM = 0x0025,
            /// <summary>C:\Program Files</summary>
            CSIDL_PROGRAM_FILES = 0x0026,
            /// <summary>C:\Program Files\My Pictures</summary>
            CSIDL_MYPICTURES = 0x0027,
            /// <summary>USERPROFILE</summary>
            CSIDL_PROFILE = 0x0028,
            /// <summary>x86 system directory on RISC</summary>
            CSIDL_SYSTEMX86 = 0x0029,
            /// <summary>x86 C:\Program Files on RISC</summary>
            CSIDL_PROGRAM_FILESX86 = 0x002a,
            /// <summary>C:\Program Files\Common</summary>
            CSIDL_PROGRAM_FILES_COMMON = 0x002b,
            /// <summary>x86 Program Files\Common on RISC</summary>
            CSIDL_PROGRAM_FILES_COMMONX86 = 0x002c,
            /// <summary>All Users\Templates</summary>
            CSIDL_COMMON_TEMPLATES = 0x002d,
            /// <summary>All Users\Documents</summary>
            CSIDL_COMMON_DOCUMENTS = 0x002e,
            /// <summary>All Users\Start Menu\Programs\Administrative Tools</summary>
            CSIDL_COMMON_ADMINTOOLS = 0x002f,
            /// <summary>[user name]\Start Menu\Programs\Administrative Tools</summary>
            CSIDL_ADMINTOOLS = 0x0030,
            /// <summary>Network and Dial-up Connections</summary>
            CSIDL_CONNECTIONS = 0x0031,
            /// <summary>All Users\My Music</summary>
            CSIDL_COMMON_MUSIC = 0x0035,
            /// <summary>All Users\My Pictures</summary>
            CSIDL_COMMON_PICTURES = 0x0036,
            /// <summary>All Users\My Video</summary>
            CSIDL_COMMON_VIDEO = 0x0037,
            /// <summary>Resource Direcotry</summary>
            CSIDL_RESOURCES = 0x0038,
            /// <summary>Localized Resource Direcotry</summary>
            CSIDL_RESOURCES_LOCALIZED = 0x0039,
            /// <summary>Links to All Users OEM specific apps</summary>
            CSIDL_COMMON_OEM_LINKS = 0x003a,
            /// <summary>USERPROFILE\Local Settings\Application Data\Microsoft\CD Burning</summary>
            CSIDL_CDBURN_AREA = 0x003b,
            /// <summary>Computers Near Me (computered from Workgroup membership)</summary>
            CSIDL_COMPUTERSNEARME = 0x003d,
            /// <summary>combine with CSIDL_ value to force folder creation in SHGetFolderPath()</summary>
            CSIDL_FLAG_CREATE = 0x8000,
            /// <summary>combine with CSIDL_ value to return an unverified folder path</summary>
            CSIDL_FLAG_DONT_VERIFY = 0x4000,
            /// <summary>combine with CSIDL_ value to avoid unexpanding environment variables</summary>
            CSIDL_FLAG_DONT_UNEXPAND = 0x2000,
            /// <summary>combine with CSIDL_ value to insure non-alias versions of the pidl</summary>
            CSIDL_FLAG_NO_ALIAS = 0x1000,
            /// <summary>combine with CSIDL_ value to indicate per-user init (eg. upgrade)</summary>
            CSIDL_FLAG_PER_USER_INIT = 0x0800
        }

        [DllImport("shell32.dll")]
        static extern bool SHGetSpecialFolderPath(IntPtr hwndOwner, [Out] StringBuilder lpszPath, int nFolder, bool fCreate);

        /// <summary></summary>
        private const string SPECIALFOLDERBRACKET = "#";

        /// <summary></summary>
        public static string ErrorState = "";

        /// <summary>
        /// 
        /// </summary>
        /// <param name="specialfoldername"></param>
        /// <returns></returns>
        public static string GetPath(string specialfoldername)
        {
            ErrorState = "";

            return getPath(specialfoldername);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="specialfoldername"></param>
        /// <returns></returns>
        private static string getPath(string specialfoldername)
        {
            StringBuilder path = new StringBuilder(260);

            try
            {
                SHGetSpecialFolderPath(IntPtr.Zero, path, (int)Enum.Parse(typeof(SpecialFolderNames), specialfoldername, true), false);
            }
            catch
            {
                ErrorState += "[" + specialfoldername + "] ist von Windows nicht unterstützt. ";

                return getPathX86(specialfoldername);
            }

            if (path.ToString().Length == 0)
            {
                ErrorState += "Wert von [" + specialfoldername + "] ist leer. ";

                return getPathX86(specialfoldername);
            }

            return path.ToString();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="specialfoldername"></param>
        /// <returns></returns>
        private static string getPathX86(string specialfoldername)
        {
            if (specialfoldername.Length > 3 && specialfoldername.Substring(specialfoldername.Length - 3, 3).Equals("X86", StringComparison.OrdinalIgnoreCase))
            {
                specialfoldername = specialfoldername.Remove(specialfoldername.Length - 3, 3);

                ErrorState += "Mit [" + specialfoldername + "] versuchen... ";

                return getPath(specialfoldername);
            }
            else
            {
                ErrorState += "[" + specialfoldername + "] ist kein X86-Pfad. ";
                return "";
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="specialfolder"></param>
        /// <returns></returns>
        public static string GetPath(SpecialFolderNames specialfolder)
        {
            return getPath(specialfolder.ToString());
        }

        /// <summary>
        /// Nicht instantiieren
        /// </summary>
        private SpecialFolder() { }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="content">Name des Spezialfolder inkl. #</param>
        /// <returns></returns>
        public static string ReplaceSpecialFolder(string content)
        {
            string result = content;

            foreach (string sfolder in GetTagParts(content, SPECIALFOLDERBRACKET))
            {
                string folderName = sfolder.Replace(SPECIALFOLDERBRACKET, "");

                string path = SpecialFolder.GetPath(folderName);

                if (path.Length > 0)
                {
                    result = result.Replace(sfolder, path);
                }
                else
                {
                    bool found = false;
                    foreach (string sfName in Enum.GetNames(typeof(SpecialFolder.SpecialFolderNames)))
                    {
                        if (folderName.Equals(sfName))
                        {
                            found = true;
                            break;
                        }
                    }

                    if (found)
                    {
                        result = "";
                    }
                }

            }

            return result;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="input"></param>
        /// <param name="tag"></param>
        /// <returns></returns>
        private static List<string> GetTagParts(string input, string tag)
        {
            List<string> output = new List<string>();
            string[] parts = input.Split(new string[] { tag }, StringSplitOptions.None);
            if (input.Length > 2 && parts.Length > 0)
            {
                for (int i = 1; i < parts.Length - 1; i++)
                {
                    output.Add(string.Format("{0}{1}{0}", tag, parts[i]));
                }
            }
            return output;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="foldername"></param>
        public static void ShowExplorerAtFolder(string foldername)
        {
            Process.Start(foldername);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="filename"></param>
        /// <returns></returns>
        public static bool ShowExplorerAtFile(string filename)
        {
            if (File.Exists(filename))
            {
                Process explorerResultProcess = new Process();
                explorerResultProcess.StartInfo.UseShellExecute = true;
                explorerResultProcess.StartInfo.FileName = "explorer.exe";
                explorerResultProcess.StartInfo.Arguments = string.Format("/e,/select,\"{0}\"", filename);
                explorerResultProcess.Start();

                return true;
            }
            else
            {
                return false;
            }
        }
    }
}
